<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>六足机器人救灾监控大屏</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #0c1445 0%, #1a2980 50%, #26d0ce 100%);
            color: #ffffff;
            overflow-x: hidden;
            min-height: 100vh;
        }

        .header {
            background: rgba(0, 0, 0, 0.3);
            backdrop-filter: blur(10px);
            padding: 20px 0;
            text-align: center;
            border-bottom: 2px solid rgba(255, 255, 255, 0.1);
        }

        .header h1 {
            font-size: 2.5em;
            font-weight: 700;
            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
            margin-bottom: 10px;
        }

        .connection-status {
            font-size: 1.1em;
            font-weight: 500;
            padding: 8px 20px;
            border-radius: 25px;
            display: inline-block;
            transition: all 0.3s ease;
        }

        .status-connected {
            background: rgba(76, 175, 80, 0.3);
            border: 2px solid #4CAF50;
            color: #4CAF50;
            box-shadow: 0 0 20px rgba(76, 175, 80, 0.3);
        }

        .status-disconnected {
            background: rgba(244, 67, 54, 0.3);
            border: 2px solid #f44336;
            color: #f44336;
            box-shadow: 0 0 20px rgba(244, 67, 54, 0.3);
        }

        .main-container {
            padding: 30px;
            max-width: 1600px;
            margin: 0 auto;
        }

        .data-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
            gap: 25px;
            margin-bottom: 30px;
        }

        .data-card {
            background: rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(15px);
            border: 1px solid rgba(255, 255, 255, 0.2);
            border-radius: 15px;
            padding: 25px;
            transition: all 0.3s ease;
            position: relative;
            overflow: hidden;
        }

        .data-card::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            height: 3px;
            background: linear-gradient(90deg, #00bcd4, #2196f3, #9c27b0);
            border-radius: 15px 15px 0 0;
        }

        .data-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 15px 35px rgba(0, 0, 0, 0.3);
            border-color: rgba(255, 255, 255, 0.3);
        }

        .data-card h3 {
            font-size: 1.4em;
            margin-bottom: 20px;
            color: #00bcd4;
            text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .data-card h3::before {
            content: '';
            width: 8px;
            height: 8px;
            background: #00bcd4;
            border-radius: 50%;
            box-shadow: 0 0 10px #00bcd4;
        }

        .data-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin: 12px 0;
            padding: 8px 0;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        }

        .data-item:last-child {
            border-bottom: none;
        }

        .data-label {
            font-weight: 500;
            color: #b0bec5;
        }

        .data-value {
            font-weight: 700;
            color: #ffffff;
            font-size: 1.1em;
            text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
        }

        .video-section {
            background: rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(15px);
            border: 1px solid rgba(255, 255, 255, 0.2);
            border-radius: 15px;
            padding: 30px;
            text-align: center;
            position: relative;
            overflow: hidden;
        }

        .video-section::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            height: 3px;
            background: linear-gradient(90deg, #ff5722, #ff9800, #ffc107);
            border-radius: 15px 15px 0 0;
        }

        .video-section h3 {
            font-size: 1.6em;
            margin-bottom: 20px;
            color: #ff9800;
            text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
        }

        .video-container {
            position: relative;
            width: 100%;
            max-width: 800px;
            margin: 0 auto;
            border-radius: 10px;
            overflow: hidden;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
        }

        .video-container video {
            width: 100%;
            height: auto;
            display: block;
        }

        .video-url {
            margin-top: 15px;
            font-size: 0.9em;
            color: #b0bec5;
            word-break: break-all;
        }

        .pulse {
            animation: pulse 2s infinite;
        }

        @keyframes pulse {
            0% {
                box-shadow: 0 0 0 0 rgba(0, 188, 212, 0.7);
            }
            70% {
                box-shadow: 0 0 0 10px rgba(0, 188, 212, 0);
            }
            100% {
                box-shadow: 0 0 0 0 rgba(0, 188, 212, 0);
            }
        }

        .battery-indicator {
            display: inline-block;
            width: 60px;
            height: 20px;
            border: 2px solid #ffffff;
            border-radius: 3px;
            position: relative;
            margin-left: 10px;
        }

        .battery-indicator::after {
            content: '';
            position: absolute;
            right: -6px;
            top: 6px;
            width: 4px;
            height: 8px;
            background: #ffffff;
            border-radius: 0 2px 2px 0;
        }

        .battery-fill {
            height: 100%;
            border-radius: 1px;
            transition: all 0.3s ease;
        }

        .battery-high {
            background: linear-gradient(90deg, #4caf50, #8bc34a);
        }

        .battery-medium {
            background: linear-gradient(90deg, #ff9800, #ffc107);
        }

        .battery-low {
            background: linear-gradient(90deg, #f44336, #ff5722);
        }

        @media (max-width: 768px) {
            .data-grid {
                grid-template-columns: 1fr;
                gap: 20px;
            }
            
            .main-container {
                padding: 20px;
            }
            
            .header h1 {
                font-size: 2em;
            }
        }

        .alert-card {
            border-left-color: #f44336 !important;
            background: rgba(244, 67, 54, 0.1) !important;
            animation: alertPulse 2s infinite;
        }

        @keyframes alertPulse {
            0%, 100% {
                box-shadow: 0 0 0 0 rgba(244, 67, 54, 0.7);
            }
            50% {
                box-shadow: 0 0 0 15px rgba(244, 67, 54, 0);
            }
        }

        .alert-sound {
            display: none;
        }

        .rescue-log {
            background: rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(15px);
            border: 1px solid rgba(255, 255, 255, 0.2);
            border-radius: 15px;
            padding: 20px;
            margin-top: 20px;
            max-height: 300px;
            overflow-y: auto;
        }

        .rescue-log h3 {
            color: #ff9800;
            margin-bottom: 15px;
            text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
        }

        .rescue-record {
            background: rgba(255, 255, 255, 0.05);
            border-left: 3px solid #4CAF50;
            padding: 10px;
            margin: 8px 0;
            border-radius: 5px;
            font-size: 0.9em;
        }

        .rescue-record.new {
            animation: newRecord 1s ease-out;
        }

        @keyframes newRecord {
            0% {
                transform: translateX(-100%);
                opacity: 0;
            }
            100% {
                transform: translateX(0);
                opacity: 1;
            }
        }

        .person-detected {
            color: #f44336 !important;
            font-weight: bold;
        }

        .person-not-detected {
            color: #4CAF50 !important;
        }
    </style>
</head>
<body>
    <div class="header">
        <h1>🤖 六足机器人救灾监控大屏</h1>
        <div id="connectionStatus" class="connection-status">
            <span class="loading"></span> 正在连接...
        </div>
    </div>

    <div class="main-container">
        <div class="data-grid">
            <div class="data-card pulse">
                <h3>🤖 机器人信息</h3>
                <div class="data-item">
                    <span class="data-label">机器人 ID:</span>
                    <span class="data-value" id="robotId">N/A</span>
                </div>
                <div class="data-item">
                    <span class="data-label">运行状态:</span>
                    <span class="data-value" id="robotStatus">N/A</span>
                </div>
                <div class="data-item">
                    <span class="data-label">最后更新:</span>
                    <span class="data-value" id="timestamp">N/A</span>
                </div>
            </div>

            <div class="data-card">
                <h3>📍 位置信息</h3>
                <div class="data-item">
                    <span class="data-label">经度:</span>
                    <span class="data-value" id="longitude">N/A</span>
                </div>
                <div class="data-item">
                    <span class="data-label">纬度:</span>
                    <span class="data-value" id="latitude">N/A</span>
                </div>
                <div class="data-item">
                    <span class="data-label">海拔高度:</span>
                    <span class="data-value" id="altitude">N/A</span>
                </div>
            </div>

            <div class="data-card">
                <h3>🧭 姿态信息</h3>
                <div class="data-item">
                    <span class="data-label">横滚角 (Roll):</span>
                    <span class="data-value" id="roll">N/A</span>
                </div>
                <div class="data-item">
                    <span class="data-label">俯仰角 (Pitch):</span>
                    <span class="data-value" id="pitch">N/A</span>
                </div>
                <div class="data-item">
                    <span class="data-label">偏航角 (Yaw):</span>
                    <span class="data-value" id="yaw">N/A</span>
                </div>
            </div>

            <div class="data-card" id="personDetectionCard">
                <h3>🚨 人员检测</h3>
                <div class="data-item">
                    <span class="data-label">检测状态:</span>
                    <span class="data-value" id="personDetected">未检测到</span>
                </div>
                <div class="data-item">
                    <span class="data-label">当前人数:</span>
                    <span class="data-value" id="currentPersonCount">0</span>
                </div>
                <div class="data-item">
                    <span class="data-label">累计发现:</span>
                    <span class="data-value" id="totalPersonCount">0 人</span>
                </div>
                <div class="data-item">
                    <span class="data-label">检测置信度:</span>
                    <span class="data-value" id="detectionConfidence">N/A</span>
                </div>
            </div>

            <div class="data-card">
                <h3>🔋 电池与传感器</h3>
                <div class="data-item">
                    <span class="data-label">电池电量:</span>
                    <span class="data-value" id="batteryLevel">
                        N/A
                        <div class="battery-indicator">
                            <div class="battery-fill" id="batteryFill"></div>
                        </div>
                    </span>
                </div>
                <div class="data-item">
                    <span class="data-label">环境温度:</span>
                    <span class="data-value" id="temperature">N/A</span>
                </div>
                <div class="data-item">
                    <span class="data-label">环境湿度:</span>
                    <span class="data-value" id="humidity">N/A</span>
                </div>
                <div class="data-item">
                    <span class="data-label">一氧化碳 (CO):</span>
                    <span class="data-value" id="gasCO">N/A</span>
                </div>
                <div class="data-item">
                    <span class="data-label">甲烷 (CH4):</span>
                    <span class="data-value" id="gasCH4">N/A</span>
                </div>
            </div>
        </div>

        <div class="video-section">
            <h3>📹 实时摄像头图像</h3>
            <div class="video-container">
                <img id="cameraImage" src="" alt="机器人摄像头图像" style="width: 100%; height: auto; display: none; border-radius: 10px;">
                <div id="noImagePlaceholder" style="width: 100%; height: 300px; background: rgba(255,255,255,0.1); border-radius: 10px; display: flex; align-items: center; justify-content: center; color: #b0bec5;">
                    等待图像数据...
                </div>
            </div>
            <div class="video-url">
                图像更新频率: 每10秒 | 最后更新: <span id="imageTimestamp">N/A</span>
            </div>
        </div>

        <div class="rescue-log">
            <h3>📋 救援记录</h3>
            <div id="rescueRecords">
                <div class="rescue-record">
                    <strong>系统启动</strong> - 等待人员检测数据...
                </div>
            </div>
        </div>
    </div>

    <!-- 报警音频 -->
    <audio id="alertSound" class="alert-sound" preload="auto">
        <source src="data:audio/wav;base64,UklGRnoGAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQoGAACBhYqFbF1fdJivrJBhNjVgodDbq2EcBj+a2/LDciUFLIHO8tiJNwgZaLvt559NEAxQp+PwtmMcBjiR1/LMeSwFJHfH8N2QQAoUXrTp66hVFApGn+DyvmwhBSuBzvLZiTYIG2m98OScTgwOUarm7blmGgU7k9n1unEiBC13yO/eizEIHWq+8+OWT" type="audio/wav">
    </audio>

    <script>
        const connectionStatus = document.getElementById('connectionStatus');
        const robotId = document.getElementById('robotId');
        const robotStatus = document.getElementById('robotStatus');
        const timestamp = document.getElementById('timestamp');
        const longitude = document.getElementById('longitude');
        const latitude = document.getElementById('latitude');
        const altitude = document.getElementById('altitude');
        const roll = document.getElementById('roll');
        const pitch = document.getElementById('pitch');
        const yaw = document.getElementById('yaw');
        const batteryLevel = document.getElementById('batteryLevel');
        const batteryFill = document.getElementById('batteryFill');
        const temperature = document.getElementById('temperature');
        const humidity = document.getElementById('humidity');
        const gasCO = document.getElementById('gasCO');
        const gasCH4 = document.getElementById('gasCH4');
        const cameraImage = document.getElementById('cameraImage');
        const noImagePlaceholder = document.getElementById('noImagePlaceholder');
        const imageTimestamp = document.getElementById('imageTimestamp');
        
        // 人员检测相关元素
        const personDetected = document.getElementById('personDetected');
        const currentPersonCount = document.getElementById('currentPersonCount');
        const totalPersonCount = document.getElementById('totalPersonCount');
        const detectionConfidence = document.getElementById('detectionConfidence');
        const personDetectionCard = document.getElementById('personDetectionCard');
        const rescueRecords = document.getElementById('rescueRecords');
        const alertSound = document.getElementById('alertSound');
        
        // 全局变量
        let totalPersonsFound = 0;
        let rescueRecordCounter = 0;

        function updateBatteryIndicator(level) {
            if (level !== undefined && level !== null) {
                const percentage = Math.max(0, Math.min(100, level));
                batteryFill.style.width = percentage + '%';
                
                // Update battery color based on level
                batteryFill.className = 'battery-fill';
                if (percentage > 60) {
                    batteryFill.classList.add('battery-high');
                } else if (percentage > 30) {
                    batteryFill.classList.add('battery-medium');
                } else {
                    batteryFill.classList.add('battery-low');
                }
            }
        }

        function playAlertSound() {
            try {
                alertSound.currentTime = 0;
                alertSound.play().catch(e => {
                    console.log('无法播放报警音频:', e);
                });
            } catch (e) {
                console.log('报警音频播放失败:', e);
            }
        }

        function addRescueRecord(personCount, location, confidence) {
            rescueRecordCounter++;
            const timestamp = new Date().toLocaleString('zh-CN');
            const record = document.createElement('div');
            record.className = 'rescue-record new';
            record.innerHTML = `
                <strong>救援记录 #${rescueRecordCounter}</strong><br>
                时间: ${timestamp}<br>
                发现人数: ${personCount} 人<br>
                位置: 经度 ${location.longitude.toFixed(6)}°, 纬度 ${location.latitude.toFixed(6)}°<br>
                置信度: ${(confidence * 100).toFixed(1)}%
            `;
            
            // 插入到记录列表顶部
            rescueRecords.insertBefore(record, rescueRecords.firstChild);
            
            // 限制记录数量，保留最新的20条
            const records = rescueRecords.querySelectorAll('.rescue-record');
            if (records.length > 20) {
                rescueRecords.removeChild(records[records.length - 1]);
            }
            
            // 滚动到顶部显示新记录
            rescueRecords.scrollTop = 0;
            
            // 立即保存到本地存储
            saveRescueRecordsToStorage();
        }

        function updatePersonDetection(data) {
            if (data.person_detected) {
                // 检测到人员
                personDetected.textContent = '🚨 检测到人员!';
                personDetected.className = 'data-value person-detected';
                currentPersonCount.textContent = data.person_count || 0;
                detectionConfidence.textContent = data.detection_confidence ? 
                    (data.detection_confidence * 100).toFixed(1) + '%' : 'N/A';
                
                // 更新累计人数
                totalPersonsFound += data.person_count || 0;
                totalPersonCount.textContent = totalPersonsFound + ' 人';
                
                // 添加报警效果
                personDetectionCard.classList.add('alert-card');
                
                // 播放报警音
                playAlertSound();
                
                // 添加救援记录
                if (data.location) {
                    addRescueRecord(data.person_count, data.location, data.detection_confidence);
                }
                
                // 5秒后移除报警效果
                setTimeout(() => {
                    personDetectionCard.classList.remove('alert-card');
                }, 5000);
                
            } else {
                // 未检测到人员
                personDetected.textContent = '未检测到';
                personDetected.className = 'data-value person-not-detected';
                currentPersonCount.textContent = '0';
                detectionConfidence.textContent = 'N/A';
                personDetectionCard.classList.remove('alert-card');
            }
        }

        const connectWebSocket = () => {
            // Use wss:// for HTTPS, ws:// for HTTP
            const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
            // Replace with your backend's IP/domain if not running on the same host
            const ws = new WebSocket(`${wsProtocol}//${window.location.host}/ws`);

            ws.onopen = () => {
                console.log('WebSocket connected');
                connectionStatus.innerHTML = '✅ 连接状态: 已连接';
                connectionStatus.className = 'connection-status status-connected';
            };

            ws.onmessage = (event) => {
                try {
                    const message = JSON.parse(event.data);
                    console.log('Received message:', message);

                    // Handle both direct robot data and wrapped message format
                    let data = message;
                    if (message.type === 'robot_status_update' && message.data) {
                        data = message.data;
                    }

                    // Update robot information
                    if (data.robot_id) robotId.textContent = data.robot_id;
                    if (data.status) robotStatus.textContent = data.status;
                    if (data.timestamp) {
                        timestamp.textContent = new Date(data.timestamp * 1000).toLocaleString('zh-CN');
                    }

                    // Update location information
                    if (data.location) {
                        if (data.location.longitude !== undefined) {
                            longitude.textContent = data.location.longitude.toFixed(6) + '°';
                        }
                        if (data.location.latitude !== undefined) {
                            latitude.textContent = data.location.latitude.toFixed(6) + '°';
                        }
                        if (data.location.altitude !== undefined) {
                            altitude.textContent = data.location.altitude.toFixed(2) + ' m';
                        }
                    }

                    // Update orientation information
                    if (data.orientation) {
                        if (data.orientation.roll !== undefined) {
                            roll.textContent = data.orientation.roll.toFixed(2) + '°';
                        }
                        if (data.orientation.pitch !== undefined) {
                            pitch.textContent = data.orientation.pitch.toFixed(2) + '°';
                        }
                        if (data.orientation.yaw !== undefined) {
                            yaw.textContent = data.orientation.yaw.toFixed(2) + '°';
                        }
                    }

                    // Update battery level
                    if (data.battery_level !== undefined) {
                        batteryLevel.firstChild.textContent = data.battery_level.toFixed(1) + '%';
                        updateBatteryIndicator(data.battery_level);
                    }

                    // Update sensor data
                    if (data.sensors) {
                        if (data.sensors.temperature !== undefined) {
                            temperature.textContent = data.sensors.temperature.toFixed(1) + '°C';
                        }
                        if (data.sensors.humidity !== undefined) {
                            humidity.textContent = data.sensors.humidity.toFixed(1) + '%';
                        }
                        if (data.sensors.gas_detection) {
                            if (data.sensors.gas_detection.CO !== undefined) {
                                gasCO.textContent = data.sensors.gas_detection.CO + ' ppm';
                            }
                            if (data.sensors.gas_detection.CH4 !== undefined) {
                                gasCH4.textContent = data.sensors.gas_detection.CH4 + ' ppm';
                            }
                        }
                    }

                    // Update camera image
                    if (data.camera_image) {
                        cameraImage.src = data.camera_image;
                        cameraImage.style.display = 'block';
                        noImagePlaceholder.style.display = 'none';
                        imageTimestamp.textContent = new Date().toLocaleString('zh-CN');
                        
                        // Add a subtle animation when image updates
                        cameraImage.style.opacity = '0.5';
                        setTimeout(() => {
                            cameraImage.style.opacity = '1';
                        }, 200);
                    }

                    // Update person detection
                    updatePersonDetection(data);

                } catch (error) {
                    console.error('Error parsing message:', error);
                }
            };

            ws.onclose = () => {
                console.log('WebSocket disconnected. Reconnecting in 5 seconds...');
                connectionStatus.innerHTML = '❌ 连接状态: 已断开，正在重连...';
                connectionStatus.className = 'connection-status status-disconnected';
                setTimeout(connectWebSocket, 5000);
            };

            ws.onerror = (error) => {
                console.error('WebSocket error:', error);
                connectionStatus.innerHTML = '⚠️ 连接状态: 错误，正在重连...';
                connectionStatus.className = 'connection-status status-disconnected';
                ws.close(); // Attempt to close and trigger onclose for reconnect
            };
        };

        // Initialize WebSocket connection
        connectWebSocket();

        // 本地存储功能
        function saveRescueRecordsToStorage() {
            const records = Array.from(rescueRecords.querySelectorAll('.rescue-record')).map(record => {
                return record.innerHTML;
            });
            localStorage.setItem('rescueRecords', JSON.stringify(records));
            localStorage.setItem('totalPersonsFound', totalPersonsFound.toString());
            localStorage.setItem('rescueRecordCounter', rescueRecordCounter.toString());
        }

        function loadRescueRecordsFromStorage() {
            try {
                const savedRecords = localStorage.getItem('rescueRecords');
                const savedTotal = localStorage.getItem('totalPersonsFound');
                const savedCounter = localStorage.getItem('rescueRecordCounter');
                
                if (savedRecords) {
                    const records = JSON.parse(savedRecords);
                    rescueRecords.innerHTML = '';
                    records.forEach(recordHTML => {
                        const record = document.createElement('div');
                        record.className = 'rescue-record';
                        record.innerHTML = recordHTML;
                        rescueRecords.appendChild(record);
                    });
                }
                
                if (savedTotal) {
                    totalPersonsFound = parseInt(savedTotal);
                    totalPersonCount.textContent = totalPersonsFound + ' 人';
                }
                
                if (savedCounter) {
                    rescueRecordCounter = parseInt(savedCounter);
                }
            } catch (e) {
                console.log('加载救援记录失败:', e);
            }
        }

        // 页面加载时恢复记录
        loadRescueRecordsFromStorage();

        // 定期保存记录
        setInterval(saveRescueRecordsToStorage, 30000); // 每30秒保存一次

        // 页面卸载时保存记录
        window.addEventListener('beforeunload', saveRescueRecordsToStorage);

        // Add image loading error handling
        cameraImage.onerror = function() {
            console.error('Failed to load camera image');
            cameraImage.style.display = 'none';
            noImagePlaceholder.style.display = 'flex';
            noImagePlaceholder.textContent = '图像加载失败';
        };

        // Add smooth transition for image updates
        cameraImage.style.transition = 'opacity 0.3s ease';

        // Add some visual feedback for data updates
        function highlightUpdate(element) {
            element.style.transition = 'all 0.3s ease';
            element.style.transform = 'scale(1.05)';
            element.style.color = '#00bcd4';
            setTimeout(() => {
                element.style.transform = 'scale(1)';
                element.style.color = '#ffffff';
            }, 300);
        }

        // Monitor for data changes and add visual feedback
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                if (mutation.type === 'childList' || mutation.type === 'characterData') {
                    highlightUpdate(mutation.target);
                }
            });
        });

        // Observe all data value elements
        document.querySelectorAll('.data-value').forEach(element => {
            observer.observe(element, { childList: true, characterData: true, subtree: true });
        });
    </script>
</body>
</html>


